package cn.bugstack.springframework.aop.framework;

import cn.bugstack.springframework.aop.AdvisedSupport;
import org.aopalliance.intercept.MethodInterceptor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


/**
 * JDK 动态代理实现类，用于创建 AOP 代理。
 */
public class JdkDynamicAopProxy implements AopProxy, InvocationHandler {

    // 保存 AOP 通知和目标对象等配置信息
    private final AdvisedSupport advised;

    /**
     * 构造函数，初始化 AOP 配置信息。
     *
     * @param advised 包含 AOP 通知和目标对象等配置信息的对象。
     */
    public JdkDynamicAopProxy(AdvisedSupport advised) {
        this.advised = advised;
    }

    /**
     * 创建并返回一个 AOP 代理对象。
     *
     * @return 返回一个动态生成的代理对象，该对象实现了和目标对象相同的接口。
     */
    @Override
    public Object getProxy() {
        // 使用 JDK 动态代理生成代理实例
        return Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), advised.getTargetSource().getTargetClass(), this);
    }

    /**
     * 当通过代理对象调用方法时，此方法会被执行。
     *
     * @param proxy 代理对象本身。
     * @param method 被调用的方法。
     * @param args 方法调用时传入的参数。
     * @return 返回方法执行的结果。
     * @throws Throwable 如果方法执行过程中发生异常，则抛出。
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        // 判断当前方法是否匹配 AOP 切面配置
        if (advised.getMethodMatcher().matches(method, advised.getTargetSource().getTarget().getClass())) {
            // 如果匹配，则使用 MethodInterceptor 来拦截方法调用
            MethodInterceptor methodInterceptor = advised.getMethodInterceptor();
            return methodInterceptor.invoke(new ReflectiveMethodInvocation(advised.getTargetSource().getTarget(), method, args));
        }
        // 如果不匹配，则直接调用目标对象的方法
        return method.invoke(advised.getTargetSource().getTarget(), args);
    }

}
